#include <stdio.h>
#include <input_stream.h>
#include <unistd.h>
#include <output_stream.h>
#include <codec_factory.h>
#include <assert.h>
#include <video_process.h>
#include <audio_process.h>

int main(int argc,char* argv)
{
    //p_latency = latency_init();
  
    printf("hello c++ \n");
    const char * input_url = "rtsp://192.168.18.45:8554/live/test";
    const char * output_url = "rtsp://192.168.18.45:8554/live/test_out_1";

    auto p_input = new InputStream();  
    bool open_input_ret = p_input->open_url(input_url);  
    if(!open_input_ret) {
        printf("open url %s fail\n",input_url);
        return -1;
    }
    AVCodecParameters avcodec_video_parameters;;
    AVRational video_time_base;
    AVCodecParameters avcodec_audio_parameters;;
    AVRational audio_time_base;

    ICodec* p_audio_decoder = 0;
    ICodec* p_audio_encoder = 0;

    video_process* p_video_process = 0;
    audio_process* p_audio_process = 0;
    
    int index;
    int ret = p_input->get_video_stream_info(&avcodec_video_parameters,video_time_base,index);
    if(ret !=0 ) {
        printf("no video stream!!!\n");
        delete p_input;
        return -1;
    }
    if(p_input->has_audio()){        
        ret = p_input->get_audio_stream_info(&avcodec_audio_parameters,audio_time_base,index);

        p_audio_decoder = codec_factory::get_instance().create_codec("aac",&avcodec_audio_parameters,audio_time_base);
        p_audio_encoder = codec_factory::get_instance().create_codec("enc_aac",&avcodec_audio_parameters,audio_time_base);
    }
    auto p_out   = new Output_Stream(output_url);
  
    bool add_ret = p_out->add_stream(&avcodec_video_parameters,video_time_base);
    if(!add_ret) {
        printf("add stream fail\n");
        delete p_input;
        delete p_out;
        return -1;
    }
    if(p_input->has_audio()) {
        p_out->add_stream(&avcodec_audio_parameters,audio_time_base);
        p_audio_process = new audio_process();
    }

    auto p_decoder = codec_factory::get_instance().create_codec("h264_vpe",&avcodec_video_parameters,video_time_base);
    auto p_encoder = codec_factory::get_instance().create_codec("h264enc_vpe",&avcodec_video_parameters,video_time_base);

    p_video_process = new video_process();
    while(true) {
        AVPacket packet;        
        int ret = p_input->read_stream(&packet);
        
        if(ret == -500) {
            av_free_packet(&packet);
            continue;
        }
        if(ret != 0 && ret != -500 ) {
            printf("read packet fail\n");
            break;
        }
        //usleep(1000*40);

        AVFrame* p_frame = av_frame_alloc();
        int got = 0;

        if(p_input->is_audio(&packet)){

            int finished = 0;
            p_audio_decoder->decode(&packet,p_frame,0,got,&finished);
            if(got) {

                p_audio_process->process(p_frame,avcodec_audio_parameters.sample_rate);
                
                AVPacket* encoder_out_packet = av_packet_alloc();             
                p_audio_encoder->encode(p_frame,encoder_out_packet,got,&finished);
                if(got) {
                    ret = p_out->write_audio_frame(encoder_out_packet);            
                    if(ret !=0) {
                        printf("write audio packet fail\n");
                        break;
                    }
                }
                //ret = p_out->write_audio_frame(&packet);
                av_free_packet(encoder_out_packet);
            }       

        }else if(p_input->is_video(&packet))
        {
            int finished = 0;
             p_decoder->decode(&packet,p_frame,0,got,&finished);             

             if(got){
               
                
                p_video_process->process(p_frame);
                 AVPacket* encoder_out_packet = av_packet_alloc();
                 p_encoder->encode(p_frame,encoder_out_packet,got,&finished);                
                 //statistic_info(0,start_time,last_time,frame_out_cnt,p_latency);
                 if(got){
                    ret = p_out->write_video_frame(encoder_out_packet);
                    if(ret !=0) {
                        printf("write packet fail\n");
                        break;
                    }
                 }
                 p_out->statistic_info(0);
                 av_free_packet(encoder_out_packet);
            }            
        }
        av_frame_free(&p_frame);
        av_free_packet(&packet);        
    }
    
    //sleep(10);
    delete p_decoder;
    delete p_encoder;
    delete p_input;
    delete p_out;
    delete p_audio_decoder;
   
    return 0;
}
